import { uniqueValueColorRampList } from '#/assets/style';

class UniqueValueRender {
  constructor(map) {
    this.map = map;
    this.colorRampList = uniqueValueColorRampList;
    // 测试用
    this.customRamp = {
      name: 'city_land',
      type: 'custom',
      colors: {
        工业用地: 'rgb(127,95,63)',
        公园与绿地用地: 'rgb(0,255,0)',
        机场设施用地: 'rgb(102,102,102)',
        交通场站用地: 'rgb(128,128,128)',
        教育科研用地: 'rgb(255,127,255)',
        居住用地: 'rgb(255,255,0)',
        商务办公用地: 'rgb(255,127,127)',
        商业服务用地: 'rgb(255,0,0)',
        体育与文化用地: 'rgb(0,165,41)',
        行政办公用地: 'rgb(255,0,255)',
        医疗卫生用地: 'rgb(255,0,63)',
      },
    };
  }

  // 颜色RGB插值
  colorsInterpolation(color1, color2, count) {
    return {
      Rs: this.equalIntervalInterpolation(color1.R, color2.R, count),
      Gs: this.equalIntervalInterpolation(color1.G, color2.G, count),
      Bs: this.equalIntervalInterpolation(color1.B, color2.B, count),
    };
  }

  // 区间等间隔插值
  equalIntervalInterpolation(first, second, counts) {
    const start = Math.min(first, second); // 较小的值作为起始范围
    const end = Math.max(first, second); // 较大的值作为结束范围
    const interval = (end - start) / (counts + 1); // 计算等间隔
    const result = [];
    for (let i = 1; i <= counts; i++) {
      const number = Math.round(start + i * interval); // 计算每个数字
      result.push(number);
    }
    return result;
  }
  getColorRampArray(rampName, featureCount) {
    const colorRamp = this.colorRampList.find(
      (colorRamp) => colorRamp.name === rampName,
    );
    // console.log(colorRamp)
    let colorRampArray = [];
    const colors = colorRamp.colors;
    if (colorRamp.type === 'random') {
      for (let i = 0; i < featureCount; i++) {
        colorRampArray.push(this.getRandomColor());
      }
    } else if (colorRamp.type === 'diy') {
      for (let i = 0; i < Math.min(featureCount, 5); i++) {
        colorRampArray.push(this.rgbToColor(colors[i]));
      }
      // 唯一值多于5个
      if (featureCount > 5) {
        //  先把五个间隔点颜色清除，方便后续插值时补充到正确的4个区间内
        colorRampArray = [];
        const averageCount = Number.parseInt((featureCount - 5) / 4);
        const remainCount = (featureCount - 5) % 4;
        // 多余的不只插一轮
        if (averageCount) {
          for (let i = 0; i < colors.length - 1; i++) {
            // 先push间隔点颜色，再在间隔点后面补充在该区间插值的颜色
            colorRampArray.push(this.rgbToColor(colors[i]));
            const { Rs, Gs, Bs } = this.colorsInterpolation(
              colors[i],
              colors[i + 1],
              averageCount,
            );
            for (let j = 0; j < averageCount; j++) {
              colorRampArray.push(
                this.rgbToColor({
                  R: Rs[j],
                  G: Gs[j],
                  B: Bs[j],
                }),
              );
            }
          }
          // push最后一个间隔点颜色
          colorRampArray.push(this.rgbToColor(colors[colors.length - 1]));
        }
        // console.log(colorRampArray[colorRampArray.length - 1]);
        // 多余的不够插一轮（唯一值超过5个但少于9个）或多余的不能平均插完
        if (remainCount) {
          for (let i = 0; i < remainCount; i++) {
            // 对于情况1，+1为了保证等分的准确性；
            // 对于情况2，+1为了避免剩余的从头开始插值时与此前插值结果重合
            const { Rs, Gs, Bs } = this.colorsInterpolation(
              colors[i],
              colors[i + 1],
              averageCount + 1,
            );
            // 对于情况1，此时Rs等数组只有一个元素，无需遍历；
            // 对于情况2，此时Rs等数组不只一个元素，但只需取其中任何一个
            // (averageCount + 2) * i + 1 使得这一轮零散的插值结果落入正确的区间内
            colorRampArray.splice(
              (averageCount + 2) * i + 1,
              0,
              this.rgbToColor({
                R: Rs[0],
                G: Gs[0],
                B: Bs[0],
              }),
            );
          }
        }
      }
    }
    return colorRampArray;
  }
  getRandomColor() {
    return `#${Math.random().toString(16).slice(2, 8)}`;
  }

  // pointUniqueValueRender(options) {
  //   const { layerId, renderField, uniqueValues, colorRamp, layerOptions } = options
  //   const layout = layerOptions.layout
  //   const paint = layerOptions.paint
  //   const colorRampArray = this.getColorRampArray(colorRamp, uniqueValues.length)
  //   const paintExpressionArr = new Array()
  //   paintExpressionArr.push('case')
  //   for (const [index, val] of uniqueValues.entries()) {
  //     paintExpressionArr.push(['==', ['get', renderField], val])
  //     paintExpressionArr.push(colorRampArray[index])
  //   }
  //   paintExpressionArr.push('#000000')
  //   Object.keys(layout).forEach(key => {
  //     this.map.setLayoutProperty(layerId, key, layout[key])
  //   })
  //   Object.keys(paint).forEach(key => {
  //     this.map.setPaintProperty(layerId, key, paint[key])
  //   })
  //   this.map.setPaintProperty(layerId, 'circle-color', paintExpressionArr)
  // }
  pointUniqueValueRender(options) {
    const { layerId, renderField, uniqueValues, colorRamp, layout, paint } =
      options;
    const colorRampArray = this.getColorRampArray(
      colorRamp,
      uniqueValues.length,
    );
    const paintExpressionArr = [];
    paintExpressionArr.push('case');
    for (const [index, val] of uniqueValues.entries()) {
      paintExpressionArr.push(
        ['==', ['get', renderField], val],
        colorRampArray[index],
      );
    }
    paintExpressionArr.push('#000000');
    // 清空原先的图层属性
    const paintProps = this.map.getLayer(layerId).paint;
    Object.keys(paintProps).forEach((key) => {
      this.map.setPaintProperty(layerId, key, null);
    });
    Object.keys(layout).forEach((key) => {
      this.map.setLayoutProperty(layerId, key, layout[key]);
    });
    Object.keys(paint).forEach((key) => {
      this.map.setPaintProperty(layerId, key, paint[key]);
    });
    this.map.setPaintProperty(layerId, 'circle-color', paintExpressionArr);
  }
  // polygonUniqueValueRender(options) {
  //   const { layerId, renderField, uniqueValues, colorRamp, layerOptions } = options
  //   const layout = layerOptions.layout
  //   const paint = layerOptions.paint
  //   const colorRampArray = this.getColorRampArray(colorRamp, uniqueValues.length)
  //   // console.log(colorRampArray)
  //   const paintExpressionArr = new Array()
  //   paintExpressionArr.push('case')
  //   // paintExpressionArr.push(['get', renderField])
  //   for (const [index, val] of uniqueValues.entries()) {
  //     // console.log(index)
  //     paintExpressionArr.push(['==', ['get', renderField], val])
  //     paintExpressionArr.push(colorRampArray[index])
  //   }
  //   paintExpressionArr.push('#000000')
  //   console.log(paintExpressionArr)
  //   Object.keys(layout).forEach(key => {
  //     this.map.setLayoutProperty(layerId, key, layout[key])
  //   })
  //   Object.keys(paint).forEach(key => {
  //     this.map.setPaintProperty(layerId, key, paint[key])
  //   })
  //   this.map.setPaintProperty(layerId, 'fill-color', paintExpressionArr)
  // }
  polygonUniqueValueRender(options) {
    const { layerId, renderField, uniqueValues, colorRamp, layout, paint } =
      options;
    // console.log(colorRampArray)
    const paintExpressionArr = [];
    paintExpressionArr.push('case');
    // paintExpressionArr.push(['get', renderField])
    if (colorRamp === this.customRamp.name) {
      for (const [_index, val] of uniqueValues.entries()) {
        // console.log(index)
        paintExpressionArr.push(
          ['==', ['get', renderField], val],
          this.customRamp.colors[val],
        );
      }
    } else {
      const colorRampArray = this.getColorRampArray(
        colorRamp,
        uniqueValues.length,
      );
      for (const [index, val] of uniqueValues.entries()) {
        // console.log(index)
        paintExpressionArr.push(
          ['==', ['get', renderField], val],
          colorRampArray[index],
        );
      }
    }
    paintExpressionArr.push('#000000');
    // console.log(paintExpressionArr);
    Object.keys(layout).forEach((key) => {
      this.map.setLayoutProperty(layerId, key, layout[key]);
    });
    Object.keys(paint).forEach((key) => {
      this.map.setPaintProperty(layerId, key, paint[key]);
    });
    this.map.setPaintProperty(layerId, 'fill-color', paintExpressionArr);
  }

  // polylineUniqueValueRender(options) {
  //   const { layerId, renderField, uniqueValues, colorRamp, layerOptions } = options
  //   const layout = layerOptions.layout
  //   const paint = layerOptions.paint
  //   const colorRampArray = this.getColorRampArray(colorRamp, uniqueValues.length)
  //   // console.log(colorRampArray)
  //   const paintExpressionArr = new Array()
  //   paintExpressionArr.push('case')
  //   // paintExpressionArr.push(['get', renderField])
  //   for (const [index, val] of uniqueValues.entries()) {
  //     // console.log(index)
  //     paintExpressionArr.push(['==', ['get', renderField], val])
  //     paintExpressionArr.push(colorRampArray[index])
  //   }
  //   paintExpressionArr.push('#000000')
  //   console.log(paintExpressionArr)
  //   Object.keys(layout).forEach(key => {
  //     this.map.setLayoutProperty(layerId, key, layout[key])
  //   })
  //   Object.keys(paint).forEach(key => {
  //     this.map.setPaintProperty(layerId, key, paint[key])
  //   })
  //   this.map.setPaintProperty(layerId, 'line-color', paintExpressionArr)
  // }
  polylineUniqueValueRender(options) {
    const { layerId, renderField, uniqueValues, colorRamp, layout, paint } =
      options;
    const colorRampArray = this.getColorRampArray(
      colorRamp,
      uniqueValues.length,
    );
    // console.log(colorRampArray)
    const paintExpressionArr = [];
    paintExpressionArr.push('case');
    // paintExpressionArr.push(['get', renderField])
    for (const [index, val] of uniqueValues.entries()) {
      // console.log(index)
      paintExpressionArr.push(
        ['==', ['get', renderField], val],
        colorRampArray[index],
      );
    }
    paintExpressionArr.push('#000000');
    // console.log(paintExpressionArr);
    Object.keys(layout).forEach((key) => {
      this.map.setLayoutProperty(layerId, key, layout[key]);
    });
    Object.keys(paint).forEach((key) => {
      this.map.setPaintProperty(layerId, key, paint[key]);
    });
    this.map.setPaintProperty(layerId, 'line-color', paintExpressionArr);
  }
  rgbToColor(rgb) {
    const R = rgb.R.toString(16).padStart(2, '0'); // 不满2位的在前面补0
    const G = rgb.G.toString(16).padStart(2, '0');
    const B = rgb.B.toString(16).padStart(2, '0');
    return `#${R}${G}${B}`;
  }
  uniqueValueRenderEntry(options) {
    switch (options.layerType) {
      case 'circle': {
        return this.pointUniqueValueRender(options);
      }
      case 'fill': {
        return this.polygonUniqueValueRender(options);
      }
      case 'line': {
        return this.polylineUniqueValueRender(options);
      }
      default:
    }
  }
}
export default UniqueValueRender;
